package org.force4spring.query;

/**
 * Implementation of <code>Expression</code> to capture a WHERE clause
 * condition.
 * 
 * @author Max Rudman
 */
public class ConditionExpression implements Expression {
	private Expression field;
	private String operator;
	private Expression value;
	
	protected ConditionExpression(Expression field, String operator, Expression value) {
		this.field = field;
		this.operator = operator;
		this.value = value;
	}
	
	public static Expression equals(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.EQUALS, value);
	}
	
	public static Expression notEquals(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.NOT_EQUALS, value);
	}
	
	public static Expression greaterThan(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.GREATER_THAN, value);
	}
	
	public static Expression greaterOrEquals(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.GREATER_OR_EQUALS, value);
	}
	
	public static Expression lessThan(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.LESS_THAN, value);
	}
	
	public static Expression lessOrEquals(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.LESS_OR_EQUALS, value);
	}
	
	public static Expression like(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.LIKE, value);
	}
	
	public static Expression in(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.IN, value);
	}
	
	public static Expression notIn(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.NOT_IN, value);
	}
	
	public static Expression includes(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.INCLUDES, value);
	}
	
	public static Expression excludes(Expression field, Expression value) {
		return new ConditionExpression(field, Operator.EXCLUDES, value);
	}
	
	/**
	 * @see org.force4spring.query.Expression#buildSOQL()
	 */
	public String buildSOQL() {
		StringBuffer soql = new StringBuffer();
		soql.append(field.buildSOQL());
		soql.append(" ").append(operator).append(" ");
		if (isParenRequired()) {
			soql.append("(");
		}
		soql.append(value.buildSOQL());
		if (isParenRequired()) {
			soql.append(")");
		}
		return soql.toString();
	}
	
	protected boolean isParenRequired() {
		if (operator.equals(Operator.IN)) {
			return true;
		}
		if (operator.equals(Operator.NOT_IN)) {
			return true;
		}
		if (operator.equals(Operator.INCLUDES)) {
			return true;
		}
		if (operator.equals(Operator.EXCLUDES)) {
			return true;
		}
		return false;
	}


	public interface Operator {
		public static final String EQUALS = "=";
		public static final String NOT_EQUALS = "!=";
		public static final String GREATER_THAN = ">";
		public static final String GREATER_OR_EQUALS = ">=";
		public static final String LESS_THAN = "<";
		public static final String LESS_OR_EQUALS = "<=";
		public static final String LIKE = "LIKE";
		public static final String IN = "IN";
		public static final String NOT_IN = "NOT IN";
		public static final String INCLUDES = "INCLUDES";
		public static final String EXCLUDES = "EXCLUDES";
	}
}
